Core.Test.registerTest({
	group: "scheduler",
	name: "Core.Scheduler",
	
	before: function() {
		Core.Test.Logger.activate();
	},
	
	"Should execute function once (time=10ms)": function() {
		Core.Scheduler.once(Res.Storage.ListenerA, 10);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
	},
	
	"Should execute function once (time=15ms)": function() {
		Core.Scheduler.once(Res.Storage.ListenerA, 15);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(0);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
	},
	
	"Should execute function once (time=20)": function() {
		Core.Scheduler.once(Res.Storage.ListenerA, 20);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(0);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
	},
	
	"Should execute periodic function (time=10)": function() {
		Core.Scheduler.periodic(Res.Storage.ListenerA, 10);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(2);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(3);
	},
	
	"Should execute periodic function (time=15)": function() {
		Core.Scheduler.periodic(Res.Storage.ListenerA, 15);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(0);
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(2);
	},
	
	"Should execute periodic function (time=20)": function() {
		Core.Scheduler.periodic(Res.Storage.ListenerA, 20);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(0);
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(2);
	},
	
	"Should execute periodic function with delay": function() {
		var async = Core.Scheduler.periodic(Res.Storage.ListenerA, 10);
		async.delay(30);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(2);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(3);
	},
	
	"Should execute periodic function with start & stop (1)": function() {
		var async = Core.Scheduler.periodic(Res.Storage.ListenerA, 10);
		async.stop();
		
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(0);

		async.start();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(2);
	},
	
	"Should execute periodic function with start & stop (2)": function() {
		var async = Core.Scheduler.periodic(Res.Storage.ListenerA, 10);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		async.stop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(1);
		
		async.start();
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertSize(2);
	},
	
	"Should execute multipile periodic functions": function() {
		Core.Scheduler.periodic(Res.Storage.ListenerA, 10);
		Core.Scheduler.periodic(Res.Storage.ListenerB, 15);
		Core.Scheduler.periodic(Res.Storage.ListenerC, 20);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["ListenerA notified"]);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["ListenerA notified", "ListenerB notified", "ListenerC notified", "ListenerA notified"]);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["ListenerA notified", "ListenerB notified", "ListenerC notified", "ListenerA notified",
		                             "ListenerA notified"]);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["ListenerA notified", "ListenerB notified", "ListenerC notified", "ListenerA notified",
		                             "ListenerA notified", "ListenerB notified", "ListenerC notified", "ListenerA notified"]);
	},
	
	"Should execute animation with start / stop events": function() {
		var anim = new Res.Scheduler.Animation();
		
		anim.start();
		Core.Test.Logger.assertFlow(["onStart"]);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["onStart", "run"]);

		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["onStart", "run", "run"]);
		
		anim.stop();
		Core.Test.Logger.assertFlow(["onStart", "run", "run", "onStop"]);
		
		Core.Scheduler._runLoop();
		Core.Test.Logger.assertFlow(["onStart", "run", "run", "onStop"]);
	}
});